package com.lxxin.service.impl;

import com.lxxin.dao.CommentDao;
import com.lxxin.dao.UserDao;
import com.lxxin.pojo.Comment;
import com.lxxin.pojo.Message;
import com.lxxin.pojo.User;
import com.lxxin.service.CommentService;
import com.lxxin.utils.IpAddressUtils;
import com.lxxin.utils.MD5Utils;
import com.lxxin.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CommentDao commentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private RedisUtil redisUtil;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public List<Comment> findCommentListByBlogId(Integer currentPage, Integer pageSize, Long id) {
        List<Comment> commentList = commentDao.findCommentListByBlogId(id);
        commentList.forEach(x -> x.getUser());
        List<Comment> newCommentList = dealCommentList(commentList);
        newCommentList = page(newCommentList, currentPage, pageSize);
        return newCommentList;
    }

    @Override
    public Integer findCommentsByBlogId(Long id) {
        return commentDao.findCommentsByBlogId(id);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public int saveComment(Comment comment, HttpServletRequest request) {
        comment.setCreateTime(System.currentTimeMillis());
        // 获取客户端ip地址
        String ipAddress = IpAddressUtils.getIpAddress(request);
        System.err.println("----------------------------------------"+ipAddress);
        // 从请求头中获取token信息
        String token = request.getHeader("token");
        if(!StringUtils.isEmpty(token)){
            User user = (User) redisUtil.get(token);
            if(user != null){
                // token校验通过则为管理员评论
                comment.getUser().setId(user.getId());
                comment.setAdminComment(true);
                userDao.saveUser(comment.getUser());
                return commentDao.saveComment(comment);
            }
        }
        // 普通用户评论，根据ip地址获取用户信息
        User userByIp = userDao.findUserByIp(ipAddress);
        // 判断用户是否存在
        if(userByIp != null){
            comment.getUser().setId(userByIp.getId());
            comment.getUser().setNickname(comment.getUser().getNickname());
            comment.getUser().setEmail(comment.getUser().getEmail());
            comment.getUser().setAvatar(getAvatarUrl(comment.getUser().getEmail()));
            comment.getUser().setUpdateTime(System.currentTimeMillis());
            userDao.updateUser(comment.getUser());
        }
        else {
            comment.getUser().setAvatar(getAvatarUrl(comment.getUser().getEmail()));
            comment.getUser().setIp(ipAddress);
            comment.getUser().setType(0);
            comment.getUser().setCreateTime(System.currentTimeMillis());
            comment.getUser().setUpdateTime(System.currentTimeMillis());
        }
        userDao.saveUser(comment.getUser());
        return commentDao.saveComment(comment);
    }

    /**
     * 根据邮箱获取头像
     * @param email
     * @return
     */
    public String getAvatarUrl(String email) {
        //如果是QQ邮箱
        if(email.indexOf("@qq.com") >= 0) {
            String prefix = email.replace("@qq.com", "");
            if(prefix.matches("[1-9][0-9]{4,}")) {
                return "https://q2.qlogo.cn/headimg_dl?dst_uin="+ prefix +"&spec=100";
            }
        }
        //Gravatar头像
        String md5Email = MD5Utils.code(email);
        return "http://cdn.v2ex.com/gravatar/"+ md5Email +"?s=100";
    }

    /**
     * 找到所有没有父评论的留言
     *
     * @param commentList
     * @return
     */
    public List<Comment> dealCommentList(List<Comment> commentList) {
        List<Comment> newCommentList = new ArrayList<>();
        for (Comment comment : commentList) {
            if (comment.getParentCommentId() == null) {
                newCommentList.add(comment);
                List<Comment> childList = getChildComment(comment, commentList);
                comment.setChildComments(childList);
            }
        }
        return newCommentList;
    }

    /**
     * 对顶级留言进行处理，广度优先搜索，逐个加入链表，最后按时间降序排序后返回
     *
     * @param comment
     * @param commentList
     * @return
     */
    public List<Comment> getChildComment(Comment comment, List<Comment> commentList) {
        ArrayDeque<Comment> queue = new ArrayDeque<>();
        List<Comment> childList = new ArrayList<>();
        queue.addLast(comment);
        while (!queue.isEmpty()) {
            Comment tmpParent = queue.removeFirst();
            for (Comment c : commentList) {
                if (c.getParentCommentId() != null && c.getParentCommentId().equals(tmpParent.getId())) {
                    Comment tmp = new Comment();
                    tmp.setId(tmpParent.getId());
                    tmp.setUser(tmpParent.getUser());
                    c.setParentComment(tmp);
                    childList.add(c);
                    queue.addLast(c);
                }
            }
        }
        Collections.sort(childList, (a, b) -> (int) (b.getCreateTime() - a.getCreateTime()));
        return childList;
    }

    /**
     * 对评论进行分页
     * @param commentList
     * @param currentPage
     * @param pageSize
     * @return
     */
    public List<Comment> page(List<Comment> commentList, int currentPage, int pageSize) {
        List<Comment> currentPageList = new ArrayList<>();
        if(commentList != null && commentList.size() > 0) {
            int currIdx = (currentPage > 1 ? (currentPage - 1) * pageSize : 0);
            for (int i = 0; i < pageSize && i < commentList.size() - currIdx; i++) {
                Comment data = commentList.get(currIdx + i);
                currentPageList.add(data);
            }
        }
        return currentPageList;
    }
}
